﻿using DbInfra;
using Grpc.Core;
using ImageDomain.Agg;
using ImageDomain.Utils;
using Newtonsoft.Json;
using OpenCvSharp;
using RestHttpInfras;
using RestHttpInfras.RequestEntities;
using ScienceAppService.ModuleInterface;
using ScienceRpcServe.Protos;
using ScienceRpcServe.Utils;
using ImageRecord = CommonEntity.CommonImageEntities.ImageRecord;
using SegRequest = ScienceRpcServe.Protos.SegRequest;

namespace ScienceRpcServe.Services;

public class ArmBoneSegService : ArmBoneSeg.ArmBoneSegBase
{

    private readonly ILogger<ImageShowService> _logger;
    private readonly IArmBoneSegAgg _agg;
    private readonly IHttpUtil _httpUtil;
    private readonly IImageRepository _imageRepository;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="agg"></param>
    public ArmBoneSegService(ILogger<ImageShowService> logger, IArmBoneSegAgg agg, IHttpUtil httpUtil, IImageRepository imageRepository)
    {
        _logger = logger;
        _agg = agg;
        _httpUtil = httpUtil;
        _imageRepository = imageRepository;
    }

    /// <summary>
    /// 图像上传接口
    /// </summary>
    /// <param name="request"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task<BoolResponse> UploadImageFile(EmptyRequest request, ServerCallContext context)
    {
        try
        {
            _logger.LogInformation($"{nameof(UploadImageFile)} | {JsonConvert.SerializeObject(request)}");

            var imgBytes = _agg.CtImage!.ConvertImageToByte();

            await _httpUtil.PostFileRequest(new FileRequest()
            {
                fileName = _agg.CtImage!.SeriesDescription,
                size = _agg.CtImage.OriginSize!,
                origin = _agg.CtImage.Origin!,
                direction = _agg.CtImage.Direction!,
                spacing = _agg.CtImage.Spacing!,
                imagedata = Convert.ToBase64String(imgBytes)
            });

            return new BoolResponse() { IsSuccess = true };
        }
        catch (Exception e)
        {
            _logger.LogError($"{nameof(UploadImageFile)} | {JsonConvert.SerializeObject(e)}");
            return new BoolResponse() { Remark = e.Message };
        }
    }

    /// <summary>
    /// todo 补全, 调用分割方法
    /// </summary>
    /// <param name="request"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task<BoolResponse> SegBone(SegRequest request, ServerCallContext context)
    {
        try
        {
            _logger.LogInformation($"{nameof(SegBone)} | {JsonConvert.SerializeObject(request)}");

            var segRequest = new AiSegRequest();
            if (request.UlnaPoints?.Count > 0)
            {
                segRequest.UlnaPoints = new double[request.UlnaPoints.Count, 3];
                for (var i = 0; i < request.UlnaPoints.Count; i++)
                {
                    segRequest.UlnaPoints[i, 0] = request.UlnaPoints[i].X;
                    segRequest.UlnaPoints[i, 1] = request.UlnaPoints[i].Y;
                    segRequest.UlnaPoints[i, 2] = request.UlnaPoints[i].Z;
                }
            }

            if (request.TfccPoints?.Count > 0)
            {
                segRequest.TfccPoints = new double[request.TfccPoints.Count, 3];
                for (var i = 0; i < request.TfccPoints.Count; i++)
                {
                    segRequest.TfccPoints[i, 0] = request.TfccPoints[i].X;
                    segRequest.TfccPoints[i, 1] = request.TfccPoints[i].Y;
                    segRequest.TfccPoints[i, 2] = request.TfccPoints[i].Z;
                }
            }

            if (request.RadiusPoints?.Count > 0)
            {
                segRequest.RadiusPoints = new double[request.RadiusPoints.Count, 3];
                for (var i = 0; i < request.RadiusPoints.Count; i++)
                {
                    segRequest.RadiusPoints[i, 0] = request.RadiusPoints[i].X;
                    segRequest.RadiusPoints[i, 1] = request.RadiusPoints[i].Y;
                    segRequest.RadiusPoints[i, 2] = request.RadiusPoints[i].Z;
                }
            }

            var rs = await _httpUtil.PostSegRequestNew(segRequest);

            if (!rs.is_success)
            {
                return new BoolResponse();
            }

            // 设置mask

            var image_array = rs.mask.ConvertToByteArr(_agg.CtImage!.OriginSize!);

            await _agg.SetSegMaskImage(image_array);

            // 数据保存
            await SegDataSave();

            return new BoolResponse(){IsSuccess = true};
        }
        catch (Exception e)
        {
            _logger.LogError($"{nameof(SegBone)} | {JsonConvert.SerializeObject(e)}");
            return new BoolResponse() { Remark = e.Message };
        }

    }

    /// <summary>
    /// 构建3d mask
    /// </summary>
    /// <param name="request"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public override async Task<BoolResponse> BuildDraw3d(BuildDrawRequest request, ServerCallContext context)
    {
        try
        {
            _logger.LogInformation($"{nameof(BuildDraw3d)} | {JsonConvert.SerializeObject(request)}");
            var isBuildSuccess = false;

            // 横断面
            if (request.Orientation == ImageOrientation.TransversePlane)
            {
                var axDic = new Dictionary<int, Mat>();
                foreach (var mat in request.MaskMats)
                {
                    axDic[mat.Index] = mat.DrawMat.ConvertToMat()!;
                }

                if (axDic.Keys.Count > 0)
                {
                    await _agg.BuildMaskByAxMat(axDic);
                    isBuildSuccess = true;
                }
            }

            // 矢状面
            if (request.Orientation == ImageOrientation.SagittalPlane)
            {
                var sagDic = new Dictionary<int, Mat>();
                foreach (var mat in request.MaskMats)
                {
                    sagDic[mat.Index] = mat.DrawMat.ConvertToMat()!;
                }

                if (sagDic.Keys.Count > 0)
                {
                    await _agg.BuildMaskBySagMat(sagDic);
                    isBuildSuccess = true;
                }
            }

            // 冠状面
            if (request.Orientation == ImageOrientation.CoronalPlane)
            {
                var corDic = new Dictionary<int, Mat>();
                foreach (var mat in request.MaskMats)
                {
                    corDic[mat.Index] = mat.DrawMat.ConvertToMat()!;
                }

                if (corDic.Keys.Count > 0)
                {
                    await _agg.BuildMaskByCorMat(corDic);
                    isBuildSuccess = true;
                }
            }

            if (isBuildSuccess)
            {
                await SegDataSave();
            }

            return new BoolResponse() { IsSuccess = true };
        }
        catch (Exception e)
        {
            _logger.LogError($"{nameof(BuildDraw3d)} | {JsonConvert.SerializeObject(e)}");
            return new BoolResponse() { Remark = e.Message };
        }
    }

    /// <summary>
    /// 入库 并保存分割数据
    /// </summary>
    /// <returns></returns>
    async Task SegDataSave()
    {
        await _agg.SaveDataToHistory();
        _imageRepository.AddImageRecord(new ImageRecord()
        {
            SeriesDescription = _agg.CtImage!.SeriesDescription,
            Dimension = $"{_agg.CtImage.OriginSize![0]}*{_agg.CtImage.OriginSize![1]}*{_agg.CtImage.OriginSize![2]}",
            Directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "HistoryImageFolder", _agg.CtImage.SeriesDescription),
            CreateTime = DateTime.Now,
            PatientName = ""
        });
    }

}
